package cn.wp.common.core.generate;

import cn.hutool.core.collection.CollectionUtil;
import cn.wp.common.core.generate.meta.Author;
import cn.wp.common.core.generate.meta.Table;
import cn.wp.common.core.generate.meta.TableColumn;
import cn.wp.common.core.plugin.template.SimpleSpringTemplateEngine;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.thymeleaf.dialect.IDialect;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.dialect.SpringStandardDialect;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.StringTemplateResolver;
import org.yaml.snakeyaml.Yaml;

import java.sql.*;
import java.util.List;
import java.util.Map;

/**
 * 代码生成工具
 * Created by chenyb on 2019/10/22
 */
public abstract class GenerateCode {

    private Map<String,String> property2BeanMap = new LinkedCaseInsensitiveMap<>();

    // 模板引擎
    protected SimpleSpringTemplateEngine templateEngine;

    public GenerateCode(){
        templateEngine = new SimpleSpringTemplateEngine();
        IDialect dialect = new SpringStandardDialect();
        templateEngine.setDialect(dialect);

        // 文本解析器
        StringTemplateResolver resolverText = new StringTemplateResolver();
        resolverText.setCacheable(true);
        resolverText.setTemplateMode(TemplateMode.TEXT);
        // 添加解析器
        templateEngine.addTemplateResolver(resolverText);

        // 映射
        this.mapping();
    }

    private void mapping(){
        property2BeanMap.put("BIGINT UNSIGNED","Long");
        property2BeanMap.put("DATETIME","Date");
        property2BeanMap.put("TIMESTAMP","Date");
        property2BeanMap.put("VARCHAR","String");
        property2BeanMap.put("DECIMAL","BigDecimal");
        property2BeanMap.put("BIGINT","Long");
        property2BeanMap.put("TEXT","String");
        property2BeanMap.put("TINYINT","Integer");
        property2BeanMap.put("INT","Integer");
        property2BeanMap.put("BIT","Integer");
        property2BeanMap.put("CHAR","String");
    }

    public Connection getConnection(){
        Connection conn = null;
        try {
            Yaml yaml = new Yaml();
            Map<String, Object> ret = (Map<String, Object>) yaml.load(this.getClass().getClassLoader().getResourceAsStream("application-dev.yaml"));
            Map<String,Object> spring = (Map<String,Object> )ret.get("spring");
            Map<String,Object> datasource = (Map<String,Object> )spring.get("datasource");

            String url = String.valueOf(datasource.get("url"));
            String username = String.valueOf(datasource.get("username"));
            String password = String.valueOf(datasource.get("password"));

            conn = DriverManager.getConnection(url,username,password);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return conn;
    }

    public void closeConnection(Connection conn){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成代码
     * @return
     */
    public String genCode(Table table, Author author){
        String result = "";
        Connection conn = getConnection();
        try {
            DatabaseMetaData metaData = conn.getMetaData();
            ResultSet resultSet = metaData.getColumns(null, null, table.getCode(), "%");
            // 迭代元数据
            List<TableColumn> tableColumnList = CollectionUtil.newArrayList();
            while (resultSet.next()) {
                TableColumn tableColumn = new TableColumn();
                tableColumn.setCode(resultSet.getString("column_name").toLowerCase());
                tableColumn.setType(property2BeanMap.get(resultSet.getString("type_name")));
                tableColumn.setComment(resultSet.getString("remarks"));
                tableColumnList.add(tableColumn);
            }

            // 生成
            result = create(tpl(),table,author,tableColumnList);
            resultSet.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        // 关闭连接
        closeConnection(conn);
        return result;
    }

    /**
     * 模板构造
     * @return
     */
    protected abstract String tpl();

    /**
     * 生成代码
     * @param tpl
     * @param table
     * @param author
     * @param tableColumnList
     * @return
     */
    protected abstract String create(String tpl,Table table,Author author,List<TableColumn> tableColumnList);

}
